import pymongo
import asyncio
from fastapi import FastAPI, Form
import datetime as timedata
import yaml
import uvicorn
import os
import sys
#import pprint
import motor.motor_asyncio
import base64


apps = FastAPI()


ret = open(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])),"setting.yml"),"r",encoding="utf-8")
yamlread= ret.read()
ret.close()
liuc = yaml.load(yamlread, Loader=yaml.FullLoader)

#client = pymongo.MongoClient("localhost", 27017)

class myclientday(object):
    myday = None
    updb = None
    getdb = None
    client = None


async def getmongday():
    daytod = timedata.datetime.today()
    for uscor in await myclientday.updb.list_collection_names():
        day = daytod - timedata.datetime.strptime(uscor,"%Y-%m-%d")
        if day.days < int(liuc["time"])+1:
            return uscor
    return str(daytod)[:10]


async def whiledele(mydata):
    n = 0
    err = None
    while True:
        try:
            fittr = await mydata.next()
            await myclientday.updb[myclientday.myday].delete_one(fittr)
            n += 1
        except StopIteration:
            break
        except Exception as e:
            err = str(e)
            break
    return {"code": True, "msg":n, "error":err}


@apps.on_event("startup")
async def startup_event():
    myclientday.client = motor.motor_asyncio.AsyncIOMotorClient('localhost', 27017)
    myclientday.updb = myclientday.client['anjiudate']
    myclientday.getdb = myclientday.client['dateanjiu']
    myclientday.myday = await getmongday()


@apps.on_event("shutdown")
async def shutdown_event():
    await myclientday.client.close()


# https://www.liaoxuefeng.com/wiki/1016959663602400/1017684507717184
# post 请求
#
# 查看新增留存账号
# Ip:80/check {
#				GameName:str,
#				Model:str,
#				datatime:str,
#				Set:[lc,xz]
#				}
# 删除留存
# Ip:80/delete {
#				GameName: str,
#				Model: str,
#				datatime: str
#				}
# 新增
# Ip:80/update  {
#					phoneIMEI:str,
#					phoneIMSI:,
#					datetime: str,
#					phoneSimSerial: str,
#					phoneAndroidId: str,
#					phoneModel: str,
#					phoneManufacturer: str,
#					macAddress: str,
#					phoneNumber: str,
#					user: str,
#					password: str,
#					Channel: str,
#					GameName: str,
#					Model:str,
#					deviceID: str
#					}
# 留存
# Ip:80/getdata {
#					GameName: str,
#					Channel: str
#					}
#
# get请求
#
# 查看 
# Ip:80/check_get?GameName=我的世界&Model=新增&datatime=2021-09-24&Channel=游戏Fan&Set=lc
#
# 删除
# Ip:80/delete_get?GameName=我的世界&Model=新增&datatime=2021-09-24&Channel=游戏Fan&Set=lc&seek=100
# 
# 新增
# Ip:80/update_get?phoneIMEI=None&phoneIMSI=None&phoneSimSerial=None&phoneAndroidId=None&phoneModel=None& phoneManufacturer=None&macAddress=None&phoneNumber=None&user=None&password=None&Channel=None&GameName=None&Model=None&deviceID=None&datetime=None
#
# 留存
# Ip:80/getdata_get?GameName=我的世界&Channel=游戏Fan
#
#['uvicorn.logging','uvicorn.loops','uvicorn.loops.auto','uvicorn.protocols','uvicorn.protocols.http','uvicorn.protocols.http.auto','uvicorn.lifespan','uvicorn.lifespan.on']



@apps.get("/update_get")
async def update_get(phoneIMEI=None, phoneIMSI=None, phoneSimSerial=None, phoneAndroidId=None,phoneModel=None, phoneManufacturer=None, macAddress=None, phoneNumber=None, user=None, password=None, Channel=None, GameName=None, Model=None, deviceID=None, datetime=None):

    print("update_get",{"phoneIMEI":phoneIMEI,"phoneIMSI":phoneIMSI,"datetime":datetime,"phoneSimSerial":phoneSimSerial,"phoneAndroidId":phoneAndroidId,"phoneModel":phoneModel,"phoneManufacturer":phoneManufacturer,"macAddress":macAddress,"phoneNumber":phoneNumber,"user":user,"password":password,"Channel":Channel,"GameName":GameName,"Model":Model,"deviceID":deviceID})

    dict_ = {
    "phoneIMEI": phoneIMEI,
    "phoneIMSI": phoneIMSI,
    "phoneSimSerial": phoneSimSerial,
    "phoneAndroidId": phoneAndroidId,
    "phoneModel": phoneModel,
    "phoneManufacturer": phoneManufacturer,
    "macAddress": macAddress,
    "phoneNumber": phoneNumber,
    "user": user,
    "password": password,
    "chennl": Channel,
    "game": GameName,
    "model": Model,
    "time": datetime,
    "deviceID":deviceID
    }

    try:
        daytod = timedata.datetime.today()
        day = daytod - timedata.datetime.strptime(myclientday.myday,"%Y-%m-%d")
        if day.days > int(liuc["time"])+1:
            myclientday.myday = await getmongday()
        upret = await myclientday.updb[myclientday.myday].insert_one(dict_)
        return {"code": upret.acknowledged,"msg":str(upret.inserted_id)}
    except Exception as e:
        return {"code":False, "msg": str(e)}


@apps.get("/check_get")
async def check(GameName=None, Model=None, datatime=None, Channel=None, Set='lc'):

    print("check_get",{"GameName":GameName, "Model":Model, "datatime":datatime, "chennl":Channel, "Set":Set})

    dic = {}
    if GameName:
        dic.update({"game":GameName})
    if Model:
        dic.update({"model":Model})
    if datatime:
        dic.update({"time":datatime})
    if Channel:
        dic.update({"chennl":Channel})
    try:
        if Set == "lc":
            sums = await myclientday.getdb['data'].count_documents(dic)
        elif Set == "xz":
            sums = 0
            for uscor in await myclientday.updb.list_collection_names():
                sums += await myclientday.updb[uscor].count_documents(dic)
        else:
            sums = 0
        return {"code":True, "msg": sums}
    except Exception as e:
        return {"code":False, "msg": str(e)}


@apps.get("/delete_get")
async def delete(GameName=None, Model=None, datatime=None, Channel=None, seek=None, Set='lc'):

    print("delete_get",{"GameName":GameName, "Model":Model, "datatime":datatime, "chennl":Channel, "seek":seek, "Set":Set})

    dic = {}
    if GameName:
        dic.update({"game":GameName})
    if Model:
        dic.update({"model":Model})
    if datatime:
        dic.update({"time":datatime})
    if Channel:
        dic.update({"chennl":Channel})
    try:
        if Set == 'lc':
            if seek:
                mydata = myclientday.getdb['data'].find(dic)
                mydata.limit(int(seek))
                await whiledele(mydata)
                retdata = {"code":True}
            else:
                ret = await myclientday.getdb['data'].delete_many(dic)
                retdata = ret.raw_result
                retdata.update({"code":True})
        else:
            if seek:
                mydata = myclientday.updb[myclientday.myday].find(dic)
                mydata.limit(int(seek))
                await whiledele(mydata)
                retdata = {"code":True}
            else:
                ret = await myclientday.updb[myclientday.myday].delete_many(dic)
                retdata = ret.raw_result
                retdata.update({"code":True})
        return retdata
    except Exception as e:
        return {"code":False,"msg": str(e)}


@apps.get("/getdata_get")
async def getdata(GameName=None, Channel=None):

    print("getdata_get",{"GameName":GameName, "Channel":Channel})

    dic = {}
    if GameName:
        dic.update({"game":GameName})
    if Channel:
        dic.update({"chennl":Channel})
    game_dic = await myclientday.getdb['data'].find_one(dic)
    try:
        game_dic.pop("_id")
        ret = await myclientday.getdb['data'].delete_one(game_dic)
        if ret.deleted_count == 1:
            game_dic.update({"code":True})
            return game_dic
        else:
            return {"code":False, "msg":"删除失败"}
    except Exception as e:
        return {"code":False, "msg": str(e)}


@apps.post("/check")
async def check(
    GameName: str = Form(...),
    Model: str = Form(...),
    datatime: str = Form(...),
    Set: str = Form(...)):

    GameName = str(base64.urlsafe_b64decode(GameName).decode("utf-8"))
    Model = str(base64.urlsafe_b64decode(Model).decode("utf-8"))

    print("check_post", {"GameName":GameName, "Model":Model, "datatime":datatime, "Set":Set})

    if Set == "lc":
        sums = await myclientday.getdb['data'].count_documents({"model":Model, "game":GameName})
    elif Set == "xz":
        sums = 0
        for uscor in await myclientday.updb.list_collection_names():
            sums += await myclientday.updb[uscor].count_documents({"time":datatime,"model":Model,"game":GameName})
    else:
        sums = 0
    return {"sum":sums}


@apps.post("/delete")
async def delete(
    GameName: str = Form(...),
    Model: str = Form(...),
    datatime: str = Form(...)):

    GameName = str(base64.urlsafe_b64decode(GameName).decode("utf-8"))
    Model = str(base64.urlsafe_b64decode(Model).decode("utf-8"))

    print("delete_post",{"GameName":GameName, "Model":Model, "datatime":datatime})

    ret = await myclientday.getdb['data'].delete_many({"time":datatime, "model":Model, "game":GameName})
    return ret.raw_result


@apps.post("/update")
async def update(
    phoneIMEI: str = Form(...),
    phoneIMSI: str = Form(...),
    datetime: str = Form(...),
    phoneSimSerial: str = Form(...),
    phoneAndroidId: str = Form(...),
    phoneModel: str = Form(...),
    phoneManufacturer: str = Form(...),
    macAddress: str = Form(...),
    phoneNumber: str = Form(...),
    user: str = Form(...),
    password: str = Form(...),
    Channel: str = Form(...),
    GameName: str = Form(...),
    Model: str = Form(...),
    deviceID: str = Form(...)):

    GameName = str(base64.urlsafe_b64decode(GameName).decode("utf-8"))
    Model = str(base64.urlsafe_b64decode(Model).decode("utf-8"))
    Channel = str(base64.urlsafe_b64decode(Channel).decode("utf-8"))

    print("update_post",{"phoneIMEI":phoneIMEI,"phoneIMSI":phoneIMSI,"datetime":datetime,"phoneSimSerial":phoneSimSerial,"phoneAndroidId":phoneAndroidId,"phoneModel":phoneModel,"phoneManufacturer":phoneManufacturer,"macAddress":macAddress,"phoneNumber":phoneNumber,"user":user,"password":password,"Channel":Channel,"GameName":GameName,"Model":Model,"deviceID":deviceID})

    # 上传数据
    dict_ = {
    "phoneIMEI": phoneIMEI,
    "phoneIMSI": phoneIMSI,
    "phoneSimSerial": phoneSimSerial,
    "phoneAndroidId": phoneAndroidId,
    "phoneModel": phoneModel,
    "phoneManufacturer": phoneManufacturer,
    "macAddress": macAddress,
    "phoneNumber": phoneNumber,
    "user": user,
    "password": password,
    "chennl": Channel,
    "game": GameName,
    "model": Model,
    "time": datetime,
    "deviceID":deviceID
    }

    try:
        daytod = timedata.datetime.today()
        day = daytod - timedata.datetime.strptime(myclientday.myday,"%Y-%m-%d")
        if day.days > int(liuc["time"])+1:
            myclientday.myday = await getmongday()
        upret = await myclientday.updb[myclientday.myday].insert_one(dict_)
        return {"state": upret.acknowledged,"id":str(upret.inserted_id)}
    except Exception as e:
        return {"state": False,"error":str(e)}


@apps.post("/getdata")
async def getdata(
    GameName: str = Form(...),
    Channel: str = Form(...)):

    GameName = str(base64.urlsafe_b64decode(GameName).decode("utf-8"))
    Channel = str(base64.urlsafe_b64decode(Channel).decode("utf-8"))

    print("getdata_get", {"GameName":GameName, "Channel":Channel})

    game_dic = await myclientday.getdb['data'].find_one({"game":GameName,"chennl":Channel})
    if game_dic:
        try:
            game_dic.pop("_id")
            ret = await myclientday.getdb['data'].delete_one(game_dic)
            game_dic.update({"code":True})
            if ret.deleted_count == 1:
                return game_dic
            else:
                return {"code":False,"user":"删除失败"}
        except Exception as e:
            return {"code":False,"user": str(e)}
    else:
        return {"code":False}


if __name__ == '__main__':
    uvicorn.run(apps,host='0.0.0.0',port=9090)

